package com.bookbuf.library;

import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;

import java.lang.ref.WeakReference;

/**
 * Created by robert on 16/6/6.
 */
public class LoadingLayout extends FrameLayout implements ILoadingCallback {

	protected LoadingLayoutAdapter<?> adapter;
	protected DataSetObserver dataSetObserver;
	protected OnInflateListener onInflateListener;

	/*待切换的视图资源 id*/
	protected int mLoadingViewLayoutId;
	protected int mInitViewLayoutId;
	protected int mErrorViewLayoutId;
	protected int mEmptyViewLayoutId;
	protected int mContentViewLayoutId;

	protected int mPrevLayoutId;

	protected OnClickListener mRetryListener;

	public LoadingLayout (Context context) {
		this (context, null);
	}

	public LoadingLayout (Context context, AttributeSet attrs) {
		this (context, attrs, -1);
	}

	public LoadingLayout (Context context, AttributeSet attrs, int defStyleAttr) {
		super (context, attrs, defStyleAttr);
		TypedArray array = context.getTheme ().obtainStyledAttributes (attrs, R.styleable.LoadingLayout, 0, 0);
		if (array != null) {
			try {
				mLoadingViewLayoutId = array.getResourceId (R.styleable.LoadingLayout_loading, R.layout.content_loading);
				mInitViewLayoutId = array.getResourceId (R.styleable.LoadingLayout_init, R.layout.content_init);
				mErrorViewLayoutId = array.getResourceId (R.styleable.LoadingLayout_error, R.layout.content_error);
				mEmptyViewLayoutId = array.getResourceId (R.styleable.LoadingLayout_empty, R.layout.content_empty);
				mContentViewLayoutId = array.getResourceId (R.styleable.LoadingLayout_content, R.layout.content_content);
			} finally {
				array.recycle ();
			}
		}

	}

	public void setOnInflateListener (OnInflateListener onInflateListener) {
		this.onInflateListener = onInflateListener;
	}

	public void setRetryListener (OnClickListener mRetryListener) {
		this.mRetryListener = mRetryListener;
	}

	public void setAdapter (LoadingLayoutAdapter<?> adapter) {

		if (this.adapter != null) {
			this.adapter.unregisterDataSetObserver (this.dataSetObserver);
			this.adapter.unbind ();
		}
		this.adapter = adapter;
		if (this.adapter != null) {
			this.dataSetObserver = new LoadingLayoutDataSetObserver (this, this.adapter);
			this.adapter.registerDataSetObserver (this.dataSetObserver);
		}
		this.adapter.notifyDataSetChanged ();
	}

	private View showView (int layoutId) {
		this.mPrevLayoutId = layoutId;
		removeAllViews ();

		LayoutInflater factory = LayoutInflater.from (getContext ());
		return factory.inflate (layoutId, this);
	}

	@Override
	public void onInit () {
		showView (mInitViewLayoutId);
	}

	private View findRetryView () {
		return findViewById (R.id.loading_retry);
	}

	@Override
	public void onEmpty () {
		showView (mEmptyViewLayoutId);
		findRetryView ().setOnClickListener (mRetryListener);
	}

	@Override
	public void onContent () {
		View view = showView (mContentViewLayoutId);
		if (onInflateListener != null) {
			onInflateListener.onInflate (view);
		}
	}

	@Override
	public void onError () {
		showView (mErrorViewLayoutId);
		findRetryView ().setOnClickListener (mRetryListener);
	}

	@Override
	public void onLoading () {
		showView (mLoadingViewLayoutId);
	}

	protected class LoadingLayoutDataSetObserver extends DataSetObserver {

		private WeakReference<ILoadingCallback> loadingCallbackWeakReference;
		private WeakReference<LoadingLayoutAdapter<?>> adapterWeakReference;

		public LoadingLayoutDataSetObserver (ILoadingCallback loadingCallbackWeakReference, LoadingLayoutAdapter<?> adapterWeakReference) {
			this.loadingCallbackWeakReference = new WeakReference<> (loadingCallbackWeakReference);
			this.adapterWeakReference = new WeakReference<LoadingLayoutAdapter<?>> (adapterWeakReference);
		}

		@Override
		public void onChanged () {
			super.onChanged ();
			ILoadingCallback callback = this.loadingCallbackWeakReference.get ();
			LoadingLayoutAdapter<?> adapter = this.adapterWeakReference.get ();
			if (adapter != null && callback != null) {
				LoadingLayoutAdapter.State state = adapter.getState ();
				switch (state) {
					case INIT:
						callback.onInit ();
						break;
					case LOADING:
						callback.onLoading ();
						break;
					case SUCCESS_EMPTY:
						callback.onEmpty ();
						break;
					case SUCCESS_NOT_EMPTY:
						callback.onContent ();
						break;
					case ERROR:
						callback.onError ();
						break;
					default:
						break;
				}
			}
		}

		@Override
		public void onInvalidated () {
			super.onInvalidated ();
			// ignore ...
		}
	}

	public interface OnInflateListener {

		void onInflate (View view);
	}
}
